package com.wangku.springmvc.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wangku.springmvc.common.BaseController;
import com.wangku.springmvc.entity.PageData;
import com.wangku.springmvc.entity.WeChatAppLoginReq;
import com.wangku.springmvc.exception.SystemException;
import com.wangku.springmvc.service.BuyerUserService;
import com.wangku.springmvc.service.WxTokenService;
import com.wangku.springmvc.utils.AppResponse;
import com.wangku.springmvc.utils.DateUtil;
import com.wangku.springmvc.utils.ParamUtil;
import com.wangku.springmvc.utils.redis.RedisPoolUtil;
import com.wangku.springmvc.utils.wechat.ResponseMsg;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
import redis.clients.jedis.Jedis;

import javax.annotation.Resource;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @description: 微信登录授权，获取用户信息
 * @author: 李赛赛
 * @create: 2018-08-15 09:59
 **/
@Controller
@RequestMapping(value = "/wxChat")
public class WxCheatLoginController extends BaseController {

    private static final Logger logger = LoggerFactory.getLogger(WxCheatLoginController.class);

    public static boolean initialized = false;

    private static final String APPID = "wx3c************b8";
    private static final String SECRET = "75324***************500ae89726";

    @Resource(name = "buyerUserService")
    private BuyerUserService userService;

    @Resource(name = "wxTokenService")
    private WxTokenService wxTokenService;
    Jedis jedis;
    @RequestMapping(value = "/login")
    @ResponseBody
    public AppResponse login(WeChatAppLoginReq req) throws Exception {
        JSONObject data = new JSONObject();
        jedis = RedisPoolUtil.getConnect();
        //获取 session_key 和 openId
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + APPID + "&secret=" + SECRET + "&js_code=" + req.getCode() + "&grant_type=authorization_code";
        RestTemplate restTemplate = new RestTemplate();
        Map map = new HashMap();
        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
        if (responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
            String sessionData = responseEntity.getBody();
            logger.info("sessionData = " + sessionData);
            JSONObject jsonObj = JSON.parseObject(sessionData);
            String openId = jsonObj.getString("openid");
            String sessionKey = jsonObj.getString("session_key");


//            String signature = HmacUtil.SHA1(req.getRawData() + sessionKey);//签名
//            if (!signature.equals(req.getSignature())) {
//                logger.info(" req signature=" + req.getSignature());
//                logger.info(" java signature=" + req.getSignature());
//                return AppResponse.error(ResponseMsg.WECHAT_LOGIN_SIGNATURE_ERROR);
//            }



            byte[] resultByte = null;
            try {
            resultByte = decrypt(Base64.decode(req.getEncryptedData()), Base64.decode(sessionKey), Base64.decode(req.getIv()));
            } catch (Exception e) {
                throw new SystemException(ResponseMsg.WECHAT_LOGIN_USER_ERROR);
            }

            if (null != resultByte && resultByte.length > 0) {
                String userInfoStr = "";
                try {
                    userInfoStr = new String(resultByte, "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    logger.error(e.getMessage());
                }
                logger.info("userInfo = " + userInfoStr);
                JSONObject userInfoObj = JSON.parseObject(userInfoStr);

                PageData userPo = new PageData();
                userPo.put("UserName", userInfoObj.getString("nickName"));
                userPo.put("CreateTime", new Date());
                userPo.put("Gender", userInfoObj.getString("gender"));
//                userPo.setIcon(userInfoObj.getString("avatarUrl"));
                userPo.put("UnionId", userInfoObj.getString("unionId"));
                userPo.put("OpenId", userInfoObj.getString("openId"));
                userPo.put("LoginType", 3);
                //根据unionId  查询用户是否注册成功
                PageData wxUserInfo = userService.findById(userPo);

                // 3登录信息放入token
                Map<String, String> dataMap = new HashMap<>();

                if (null != wxUserInfo && !"".equals(wxUserInfo)) {
                    //登录成功保村登录时间
                    wxUserInfo.put("LoginTime", DateUtil.getTime());
                    userService.editByUserId(wxUserInfo);
                    dataMap.put("BuyerUserId", ParamUtil.getString(wxUserInfo, "BuyerUserId", null));
                } else {
                    String time = String.valueOf(new Date().getTime());
                    userPo.put("LoginName", time.substring(time.length() - 11));//小程序登录生成一个LoginName
                    //新注册用户
                    //1.保存用户信息
                    userService.save(userPo);
                    dataMap.put("BuyerUserId", ParamUtil.getString(userPo, "BuyerUserId", null));
                }
                dataMap.put("LoginName", ParamUtil.getString(userPo, "LoginName", null));
                dataMap.put("OpenId", ParamUtil.getString(userPo, "OpenId", null));
                dataMap.put("UserName", ParamUtil.getString(userPo, "UserName", null));
                dataMap.put("UnionId", ParamUtil.getString(userPo, "UnionId", null));
                dataMap.put("deviceToken", ParamUtil.getString(userPo, "deviceToken", null));
                dataMap.put("loginTime", DateUtil.getTime());
                //2.存储登录标识到redis中
                String token = wxTokenService.createToken(dataMap);
                data.put("deviceToken", token);
                data.put("data", dataMap);
                //3.返回用户登录成功and标识
                return AppResponse.success(data);
            } else {
                return AppResponse.error(ResponseMsg.WECHAT_LOGIN_USER_ERROR);
            }
        }
        return AppResponse.error(ResponseMsg.WECHAT_LOGIN_USER_ERROR);
    }
    @RequestMapping(value = "/test")
    public String test(){
        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("LoginName", "18310146930");
        dataMap.put("OpenId", "14832215645154656132");
        dataMap.put("UserName", "妍兮霸霸");
        dataMap.put("BuyerUserId", "2434");
        dataMap.put("UnionId", "8886667744321");
        dataMap.put("deviceToken", "248fa6797b4142a6a995aceb3497c4ed");
        dataMap.put("loginTime", DateUtil.getTime());
        //2.存储登录标识到redis中
        String token = wxTokenService.createToken(dataMap);
        return token;
    }
    private byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException {
        initialize();
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            Key sKeySpec = new SecretKeySpec(keyByte, "AES");

            cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化
            byte[] result = cipher.doFinal(content);
            return result;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
    public static void initialize(){
        if (initialized) return;
        Security.addProvider(new BouncyCastleProvider());
        initialized = true;
    }
    //生成iv
    public static AlgorithmParameters generateIV(byte[] iv) throws Exception{
        AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
        params.init(new IvParameterSpec(iv));
        return params;
    }


    public static void main(String[] args) {
        String token = UUID.randomUUID().toString().replace("-", "");
        System.out.println(token);
    }
}
